package com.zmzncs.lmtc.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import okhttp3.internal.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class HttpUtil {

    private final static Logger logger = LoggerFactory.getLogger(HttpUtil.class);
    private static OkHttpClient okHttpClient;
    private static final Charset CHARSET_UTF8 = Charset.forName("UTF-8");


    private static class OkHttpUtilHolder {
        private static final HttpUtil INSTANCE = new HttpUtil();
    }

    public static HttpUtil getIntance() {
        return OkHttpUtilHolder.INSTANCE;
    }

    private HttpUtil(){
        okHttpClient = new OkHttpClient().newBuilder().
                connectTimeout(10, TimeUnit.SECONDS).
                readTimeout(20, TimeUnit.SECONDS).
                connectionPool(new ConnectionPool(Runtime.getRuntime().availableProcessors()*4,5L, TimeUnit.MINUTES)).build();
    }

    static public String requestGet(String url, Map<String, String> params, Map<String, String> heads) {

        OkHttpClient okHttpClient = new OkHttpClient();

        Request.Builder reqBuild = new Request.Builder();
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();

        if (params != null) {
            for (String key : params.keySet()) {
                System.out.println("key:"+key+" value:"+params.get(key));
                urlBuilder.addQueryParameter(key, params.get(key));
            }
        }


        reqBuild.url(urlBuilder.build());

        if (heads != null) {
            for (String key : heads.keySet()) {
                System.out.println("heads:"+heads);
                reqBuild.addHeader(key, heads.get(key));
            }
        }

        Request req = reqBuild.build();

        try {
            Response response = okHttpClient.newCall(req).execute();
            //判断请求是否成功
            if (response.isSuccessful()) {
                return response.body().string();
                //打印服务端返回结果
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.toString());
        }

        return null;
    }

    static public String requestPost(String url) {
        OkHttpClient okHttpClient = new OkHttpClient();

        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.post(Util.EMPTY_REQUEST);
        Request req = builder.build();

        try {
            Response response = okHttpClient.newCall(req).execute();

            logger.info("response:"+response);
            if (response.isSuccessful()) {
                return response.body().string();
            }else {
                logger.info("Unexpected code :" + JSON.toJSONString(response));
            }
        } catch (Exception e) {
            logger.error(" requestPostBody error!", e);
        }
        return null;
    }

    static public String requestDel(String url) {

        OkHttpClient okHttpClient = new OkHttpClient();

        Request.Builder builder = new Request.Builder();
        builder.url(url);
        builder.delete();
        Request req = builder.build();
        try {
            Response response = okHttpClient.newCall(req).execute();

            logger.info("response:"+response);
            if (response.isSuccessful()) {
                return response.body().string();
            }else {
                logger.info("Unexpected code :" + JSON.toJSONString(response));
            }
        } catch (Exception e) {
            logger.error(" requestPostBody error!", e);
        }
        return null;

    }

    static public String requestPostBody(String url, String json, Map<String, String> headers) {
        OkHttpClient okHttpClient = new OkHttpClient();

        MediaType JSONType = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSONType, json);

        Request.Builder builder = new Request.Builder();
        builder.url(url);
        if (headers != null) {
            for (String key : headers.keySet()) {
                builder.addHeader(key, headers.get(key));
            }
        }

        builder.post(body);
        Request request = builder.build();

        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful()) {
                return response.body().string();
                //打印服务端返回结果
            }else {
                throw new IOException("请求失败：" + response);
            }
        } catch (Exception e) {
            logger.error("请求失败：", e);
        }
        return null;
    }

    static public JSONObject requestPostBodySSO(String url, String json, Map<String, String> heads) {
        OkHttpClient okHttpClient = new OkHttpClient();

        MediaType JSONType = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSONType, json);
        Request.Builder builder = new Request.Builder();
        builder.url(url);
        if (heads != null) {
            for (String key : heads.keySet()) {
                builder.addHeader(key, heads.get(key));
            }
        }

        builder.post(body);
        Request req = builder.build();

        try {

            Response response = okHttpClient.newCall(req).execute();
            if (response.isSuccessful()) {
                JSONObject jsonObject = JSONObject.parseObject(response.body().string());
                jsonObject.put("status", "SUCCEED");
                return jsonObject;
            } else {
                JSONObject jsonObject = JSONObject.parseObject(response.body().string());
                jsonObject.put("status", "FAIL");
                return jsonObject;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    static public String requestPostForm(String url, Map<String, String> params, Map<String, String> heads) {
        OkHttpClient okHttpClient = new OkHttpClient();

        FormBody.Builder bodyBuilder = new FormBody.Builder();
        if (params != null) {
            for (String key : params.keySet()) {
                bodyBuilder.add(key, params.get(key));
            }
        }
        RequestBody body = bodyBuilder.build();
        Request.Builder builder = new Request.Builder();

        if (heads != null) {
            for (String key : heads.keySet()) {
                builder.addHeader(key, heads.get(key));
            }
        }
        builder.url(url);
        builder.post(body);

        Request req = builder.build();

        try {
            Response response = okHttpClient.newCall(req).execute();
            if (!response.isSuccessful()) {
                throw new IllegalArgumentException("数据请求失败");
            }
            return response.body().string();
            //打印服务端返回结果
        } catch (IOException e) {
            e.printStackTrace();


        }

        return null;
    }

    public String postJson(String url, String json) {
        return this.postJson(url ,json ,null);
    }

    public String post(String url, Map<String, ?> params) {
        return this.post(url,params,null);
    }


    public String get(String url) {
        return this.get(url,null,null);
    }

    public String get(String url, Map<String, Object> params) {
        return this.get(url,params,null);
    }

    public ResponseBody getBody(String url) {
        return this.getResponseBody(url,null,null);
    }

    public ResponseBody getBody(String url, Map<String, Object> params) {
        return this.getResponseBody(url,params,null);
    }


    public String post(String url, Map<String, ?> params, Map<String, String> headers) {
        String res = null;
        Response response = null;
        try {
            FormBody.Builder builder = new FormBody.Builder();
            if (params != null) {
                for (Map.Entry<String, ?> entry : params.entrySet()) {
                    if (entry != null) {
                        builder.add(entry.getKey(), entry.getValue().toString());
                    }
                }
            }
            Request.Builder header = builderHeader(headers);
            Request request = header.url(url).post(builder.build()).build();
            response = okHttpClient.newCall(request).execute();
            if(response !=null && response.body()!= null){
                res = response.body().string();
            }
        }catch (Exception e){
            logger.error("OKhttp请求异常",e);
        }finally {
            if(response != null){
                response.close();
            }
        }
        return res;
    }



    public String postJson(String url, String json , Map<String, String> headers) {
        String res = null;
        Response response = null;
        try {
            Request.Builder header = builderHeader(headers);
            Request request = header.url(url).post(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json)).build();
            response = okHttpClient.newCall(request).execute();
            if(response !=null && response.body()!= null){
                res = response.body().string();
            }
        }catch (Exception e){
            logger.error("OKhttp请求异常",e);
        }finally {
            if(response != null){
                response.close();
            }
        }
        return res;
    }



    public String get(String url, Map<String, Object> params ,Map<String, String> headers) {
        String res = null;
        Response response = null;
        try {
            if (params != null) {
                String paramStr = "";
                for (String key : params.keySet()) {
                    if (!paramStr.isEmpty()) {
                        paramStr += '&';
                    }
                    if (null == params.get(key)) {
                        paramStr += key + '=';
                    } else {
                        try {
                            paramStr += key + '=' + URLEncoder.encode(params.get(key) + "", CHARSET_UTF8.toString());
                        } catch (UnsupportedEncodingException e) {
                            logger.error("key=" + key + "," + params.get(key) + " 错误", e);
                        }
                    }
                }
                if (url.indexOf('?') > 0) {
                    url += '&' + paramStr;
                } else {
                    url += '?' + paramStr;
                }
            }
            Request.Builder header = builderHeader(headers);
            Request request = header.url(url).build();
            response = okHttpClient.newCall(request).execute();
            if(response !=null && response.body()!= null){
                res = response.body().string();
            }
        }catch (Exception e){
            logger.error("OKhttp请求异常",e);
        }finally {
            if(response != null){
                response.close();
            }
        }
        return res;
    }

    public ResponseBody getResponseBody(String url, Map<String, Object> params , Map<String, String> headers) {
        ResponseBody res = null;
        Response response = null;
        try {
            if (params != null) {
                String paramStr = "";
                for (String key : params.keySet()) {
                    if (!paramStr.isEmpty()) {
                        paramStr += '&';
                    }
                    if (null == params.get(key)) {
                        paramStr += key + '=';
                    } else {
                        try {
                            paramStr += key + '=' + URLEncoder.encode(params.get(key) + "", CHARSET_UTF8.toString());
                        } catch (UnsupportedEncodingException e) {
                            logger.error("key=" + key + "," + params.get(key) + " 错误", e);
                        }
                    }
                }
                if (url.indexOf('?') > 0) {
                    url += '&' + paramStr;
                } else {
                    url += '?' + paramStr;
                }
            }
            Request.Builder header = builderHeader(headers);
            Request request = header.url(url).build();
            response = okHttpClient.newCall(request).execute();
            if(response !=null && response.body()!= null){
                res = response.body();
            }
        }catch (Exception e){
            logger.error("OKhttp请求异常",e);
        }finally {
            if(response != null){
                response.close();
            }
        }
        return res;
    }


    /**
     * 组装header
     * @param headers
     * @return
     */
    private Request.Builder builderHeader(Map<String, String> headers){
        Request.Builder header = new Request.Builder();
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                if (entry != null) {
                    header.addHeader(entry.getKey(), entry.getValue());
                }
            }
        }
        return header;
    }

    /**
    * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
    * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？
    * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
    *
    * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130,
    * 192.168.1.100
    *
    * 用户真实IP为： 192.168.1.110
    */
     public static String getIpAddress(HttpServletRequest request) {
         String ip = request.getHeader("x-forwarded-for");
         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                 ip = request.getHeader("Proxy-Client-IP");
             }
         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                 ip = request.getHeader("WL-Proxy-Client-IP");
             }
         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                 ip = request.getHeader("HTTP_CLIENT_IP");
             }
         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                 ip = request.getHeader("HTTP_X_FORWARDED_FOR");
             }
         if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
                 ip = request.getRemoteAddr();
             }
         return ip;
     }

}
